package org.smart4j.framework.common.helper;

import com.google.common.collect.Sets;
import org.apache.commons.lang3.ClassUtils;
import org.smart4j.framework.common.util.AnnotationUtil;
import org.smart4j.framework.common.util.ClassUtil;

import java.lang.annotation.Annotation;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 加载类助手类
 * 获取基础包名下的所有类与被@Controller注解、@Service注解的类以及Bean集合
 *
 * @author YooLin1c
 * @version 1.0.0
 * @since 2018-01-30 13:10
 */
public final class ClassHelper {
    private static final Set<Class<?>> CLASS_SET;

    static {
        //根据项目的基础包名加载所有类并添加至Set集合中
        String appBasePackage = ConfigHelper.getAppBasePackage();
        CLASS_SET = ClassUtil.getClassSet(appBasePackage);
    }

    /**
     * 获取基础包名下所有的类集合
     *
     * @return
     */
    public static Set<Class<?>> getAllClassSet() {
        return CLASS_SET;
    }

    /**
     * 获取所有被@Service注解的类集合
     *
     * @return
     */
    public static Set<Class<?>> getServiceClassSet() {
        return CLASS_SET.stream().filter(AnnotationUtil::isServiceAnnotated).collect(Collectors.toSet());
    }

    /**
     * 获取所有被@Controller注解的类集合
     *
     * @return
     */
    public static Set<Class<?>> getControllerClassSet() {
        return CLASS_SET.stream().filter(AnnotationUtil::isControllerAnnotated).collect(Collectors.toSet());
    }

    /**
     * 获取所有被@Aspect注解的类集合
     *
     * @return
     */
    public static Set<Class<?>> getAspectClassSet() {
        return CLASS_SET.stream().filter(AnnotationUtil::isAspectAnnotated).collect(Collectors.toSet());
    }

    /**
     * 获取Bean容器中某父类（接口）下的所有子类（实现类）
     *
     * @param superClass 某父类/接口
     * @return
     */
    public static Set<Class<?>> getClassSetBySuper(Class<?> superClass) {
        return CLASS_SET.stream().filter(clazz -> superClass.isAssignableFrom(clazz) && !superClass.equals(clazz))
                .collect(Collectors.toSet());
    }

    /**
     * 获取Bean容器中具有指定注解的Bean对象
     *
     * @param annotation 指定注解
     * @return
     */
    public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotation) {
        return CLASS_SET.stream().filter(clazz -> AnnotationUtil.isAnnotated(clazz, annotation)).collect(Collectors.toSet());
    }

    /**
     * 获取所有的Bean集合
     *
     * @return
     */
    public static Set<Class<?>> getBeanClassSet() {
        return Sets.union(getServiceClassSet(), getControllerClassSet());
    }
}
